//*******************************************************************       //
//IMPORTANT NOTICE                                                          //
//================                                                          //
//Copyright Mentor Graphics Corporation 1996 - 1999.  All rights reserved.  //
//This file and associated deliverables are the trade secrets,              //
//confidential information and copyrighted works of Mentor Graphics         //
//Corporation and its licensors and are subject to your license agreement   //
//with Mentor Graphics Corporation.                                         //
//                                                                          //
//Use of these deliverables for the purpose of making silicon from an IC    //
//design is limited to the terms and conditions of your license agreement   //
//with Mentor Graphics If you have further questions please contact Mentor  //
//Graphics Customer Support.                                                //
//                                                                          //
//This Mentor Graphics core (m8051w v2002.080) was extracted on             //
//workstation hostid 8316cbec Inventra                                      //
// M8051W/EW and OCI Test Wrapper
// 
// $Log: m8051w_wrapper.v,v $
// Revision 1.1  2002/01/09
// changes for version 2
//
// Revision 1.1  2001/11/14
// First EW checkin
//
// Revision 1.5  2000/03/28
// OCI update
//
//
////////////////////////////////////////////////////////////////////////////////
//
// Purpose      :       M8051W/EW Soft Core 40-pin wrapper.
//                      This module instantiates the M8051W/EW and OCI cores
//                      with port I/O cells, internal RAM and internal program
//                      ROM in order to model the pinout of a discrete device.
//                      This code is a behavioural (logical) model only.
//
////////////////////////////////////////////////////////////////////////////////

`include "m8051w_cfg.v"
`include "m8051w_tb_cfg.v"

module m8051w_wrapper (PORT0, PORT1, PORT2, PORT3, XTAL2, NPSEN, XTAL1,
//*******************************************************************       //
//IMPORTANT NOTICE                                                          //
//================                                                          //
//Copyright Mentor Graphics Corporation 1996 - 1999.  All rights reserved.  //
//This file and associated deliverables are the trade secrets,              //
//confidential information and copyrighted works of Mentor Graphics         //
//Corporation and its licensors and are subject to your license agreement   //
//with Mentor Graphics Corporation.                                         //
//                                                                          //
//Use of these deliverables for the purpose of making silicon from an IC    //
//design is limited to the terms and conditions of your license agreement   //
//with Mentor Graphics If you have further questions please contact Mentor  //
//Graphics Customer Support.                                                //
//                                                                          //
//This Mentor Graphics core (m8051w v2002.080) was extracted on             //
//workstation hostid 8316cbec Inventra                                      //
                        RST, TRESET);
               
// Ports
  inout  [7:0]  PORT0;                // True bi-directional open drain port
  inout  [7:0]  PORT1;                // Quasi bi-directional port with pull-ups
  inout  [7:0]  PORT2;                // Quasi bi-directional port with pull-ups
  inout  [7:0]  PORT3;                // Quasi bi-directional port with pull-ups

  output        XTAL2;                // Inverted clock for crystal oscillator
  output        NPSEN;                // Program store enable (active low)

  input         RST;                  // Compatible Reset
  input         TRESET;               // Simulator and Test Reset Only
  input         XTAL1;                // Clock Input

  tri    [7:0]  PORT0;
  tri1   [7:0]  PORT1, PORT2, PORT3;
  tri1   [7:0]  XRAMDI, SOURCE_DI;
  tri    [7:0]  PROGDI, XRAMD;
  tri0   [13:0] XINTR_SRC;
  wire   [7:0]  MuxedPROGDI;
  wire   [7:0]  ESFRDI, ESFRDI0, ESFRDI1;
  wire   [7:0]  PORT0O, PORT1O, PORT2O, PORT3O;
  wire   [7:0]  PORT0I, PORT1I, PORT2I, PORT3I;
  wire   [7:0]  NPORT1E, NPORT2E, NPORT3E;
  wire   [13:0] XINTR_ACK;
  wire   [7:0]  XRAMDO;
  wire   [7:0]  CPDM_DO;          // combined memory data output with tri-state
  wire          CPDM_RNW;         // combined clocked memory write enable
  wire          CPDM_NCS;         // combined clocked memory device enable
  wire          NCPDM_W, NCPDM_R; // combined asynchronous memory strobes
  wire   [19:0] PROGA, XRAMA;
  wire   [7:0]  SOURCE_A, DESTIN_A, DESTIN_DO;
  wire   [7:0]  MXS_DO, MXS_DI;
  wire   [6:0]  SFRSA, MXS_A;
  wire          NSOURCE_RE, NDESTIN_WE, SFRWE, SFRRE, NXRAMR, NXRAMW;
  wire          NMXSRE, NMXSWE;
  wire          EXT2_OVERFLOW, EXT2_TCLK, EXT2_RCLK;
  wire          NXRAMW_S, NPSWR_STROBE;           // clock-gated write strobes
  wire          IDLE, PDOWN, NCCLKE, NPCLKE;
  wire   [7:0]  DO1;
  wire          SCLK, CCLK, PCLK;
  wire          NPR_EN, NPR_WE;    // derived clocked memory strobes
  wire          MWAIT;                            // Wait request

// Debugger OCI signals
  wire          TCK, TMS, TDI, TDO, TrigOut;                 // JTAG interface
  wire          DebugAck, DebugPFetch, DebugRetract, JReset; // Debug i/f
  wire          DebugVector, DebugReq, DebugStep, DebugProg; // Debug i/f
  wire   [7:0]  DebugPROGDI;                                 // Debug i/f
  wire   [3:0]  PROGB, SFRB;                                 // Debug bank i/f
  wire   [7:0]  TraceA;                                      // Debug memory i/f
  wire  [19:0]  TraceDI, TraceDO;                            // Debug memory i/f
  wire   [3:0]  SeqA;                                        // Debug memory i/f
  wire  [13:0]  SeqDI, SeqDO;                                // Debug memory i/f
  
// Instantiate the M8051EW Soft Core
m8051w uDUT(.PORT0O(PORT0O), .PORT1O(PORT1O), .PORT2O(PORT2O), .PORT3O(PORT3O),
             .NPORT1E(NPORT1E), .NPORT2E(NPORT2E), .NPORT3E(NPORT3E),
             .XRAMDO(XRAMDO), .PROGA(PROGA[`AddrSize-1:0]),
             .XRAMA(XRAMA[`AddrSize-1:0]), .NPSEN(NPSEN),
             .NPSWR(NPSWR), .NXRAMR(NXRAMR), .NXRAMW(NXRAMW), 
             .PROGA_EN(PROGA_EN), .XRAMA_EN(XRAMA_EN),
             .SOURCE_A(SOURCE_A), .DESTIN_A(DESTIN_A), .DESTIN_DO(DESTIN_DO),
             .NDESTIN_WE(NDESTIN_WE), .NSOURCE_RE(NSOURCE_RE),
             .SFRWE(SFRWE), .SFRRE(SFRRE), .SFRSA(SFRSA),
             .MXS_DO(MXS_DO), .MXS_A(MXS_A), .NMXSRE(NMXSRE), .NMXSWE(NMXSWE),
             .XINTR_ACK(XINTR_ACK), .NMI_ACK(NMI_ACK),
             .DebugAck(DebugAck), .DebugRetract(DebugRetract),
             .DebugPFetch(DebugPFetch), .DebugVector(DebugVector),
             .IDLE(IDLE), .PDOWN(PDOWN), .NCCLKE(NCCLKE), .NPCLKE(NPCLKE),
             .PORT0I(PORT0), .PORT1I(PORT1), .PORT2I(PORT2), .PORT3I(PORT3),
             .PROGDI(MuxedPROGDI), .XRAMDI(XRAMDI), .SOURCE_DI(SOURCE_DI),
             .MXS_DI(MXS_DI), .ESFRDI(ESFRDI), .XINTR_SRC(XINTR_SRC), .NMI(NMI),
             .EXT2_OVERFLOW(EXT2_OVERFLOW),
             .EXT2_TCLK(EXT2_TCLK), .EXT2_RCLK(EXT2_RCLK),
             .MWAIT(MWAIT), .DebugReq(DebugReq), .DebugStep(DebugStep),
             .SCLK(SCLK), .CCLK(CCLK), .PCLK(PCLK),
             .RESET(RESET), .TRESET(TRESET));

// optionally annotate the netlist with pre-layout delay estimates
`ifdef SDF
   initial
   begin
     $sdf_annotate("../gates/synop/m8051w.sdf",uDUT,,"sdf.log","MAXIMUM","1.0:1:1.0","FROM_MTM");
     `ifdef IncludeOCI
        $sdf_annotate("../gates/synop/oci.sdf",uOCI,,"sdf.log","MAXIMUM","1.0:1:1.0","FROM_MTM");
     `endif
   end
`endif

`ifdef IncludeOCI

  oci uOCI (CCLK, RST, TRESET, NPCLKE, PROGA_EN, MWAIT,
            TCK, TMS, TDI, TDO,
            DebugReq, DebugAck, DebugPFetch, DebugRetract, DebugVector,
            DebugStep, DebugProg, DebugPROGDI,
            PROGA[15:0], PROGA[19:16], NPSEN, NPSWR, MuxedPROGDI,
            XRAMA[15:0], XRAMA[19:16], NXRAMR, NXRAMW, XRAMDI, XRAMDO,
            DESTIN_A, SOURCE_A, NSOURCE_RE, NDESTIN_WE, SOURCE_DI, DESTIN_DO,
            SFRSA, SFRB, SFRWE, SFRRE, ESFRDI,
            TrigOut, JReset,
            TraceA, TraceDI, TraceDO, TraceWr,
            SeqA, SeqDI, SeqDO, SeqWr);

  // Tie off unused debugger JTAG inputs to inactive level
  assign TCK = 1'b1;
  assign TMS = 1'b1;
  assign TDI = 1'b1;
  assign PROGB = 4'h0;
  assign SFRB = 4'h0;
  assign TraceDO = 19'h00000;
  assign SeqDO = 13'h0000;

`else

  // Tie off M8051EW inputs from debugger
  assign DebugReq = 1'b0;
  assign DebugStep = 1'b0;
  assign DebugProg = 1'b0;

`endif

// Instantiate a 256 x 8-bit two-port RAM cell for internal data memory.
`ifdef sync_iram
initial
$display("Clocked Internal Data Memory");
cram #(`IramSize, `IramLines, `Tiramacc, `Tiramwwdo) uRAM
          (.CSN1(NSOURCE_RE), .CSN2(NDESTIN_WE), .CLK1(CCLK), .CLK2(CCLK),
           .A1(SOURCE_A), .RWN1(1'b1), .DI1(8'hzz), .DO1(SOURCE_DI),
           .A2(DESTIN_A), .RWN2(1'b0), .DI2(DESTIN_DO), .DO2());
  `ifdef MemExtend
   cram #(128, 7, `Tiramacc, `Tiramwwdo) uMXS
              (.CSN1(NMXSRE), .CSN2(NMXSWE), .CLK1(CCLK), .CLK2(CCLK),
               .A1(MXS_A), .RWN1(1'b1), .DI1(8'hzz), .DO1(MXS_DI),
               .A2(MXS_A), .RWN2(1'b0), .DI2(MXS_DO), .DO2());
  `endif
`else
initial
$display("Flip-Flop Internal Data Memory");
ram #(`IramSize, `IramLines, `Tiramacc, `Tiramwwdo) uRAM
         (.CSN1(NSOURCE_RE), .CSN2(NCCLKE),
          .A1(SOURCE_A), .RWN1(1'b1), .DI1(8'hzz), .DO1(SOURCE_DI),
          .A2(DESTIN_A), .RWN2(NDESTIN_WE), .DI2(DESTIN_DO), .DO2(),
          .TRESET(TRESET), .CLK(CCLK));
  `ifdef MemExtend
   ram #(128, 7, `Tiramacc, `Tiramwwdo) uMXS
            (.CSN1(NMXSRE), .CSN2(NMXSWE),
             .A1(MXS_A), .RWN1(1'b1), .DI1(8'hzz), .DO1(MXS_DI),
             .A2(MXS_A), .RWN2(1'b0), .DI2(MXS_DO), .DO2(),
             .TRESET(TRESET), .CLK(CCLK));
  `endif
`endif

// Instantiate up to 1Mbyte of 8-bit internal program RAM
`ifdef sync_pmem
   initial $display("Clocked Program and External Data Memories");
   assign NPR_EN = ~PROGA_EN;
   assign NPR_WE = NPSWR || TRESET;
   cpram uROM (.out_data(PROGDI), .in_data(XRAMDO),
               .address(PROGA[(`RomALines - 1):0]),
               .ncs(NPR_EN), .noe(NPSEN), .nwe(NPR_WE), .clk(CCLK));
`else
   initial $display("Asynchronous Program and External Data Memories");
   assign NPSWR_STROBE = NPSWR || CCLK;
   pram uROM (.out_data(PROGDI), .in_data(XRAMDO),
             .address(PROGA[(`RomALines - 1):0]),
             .ncs(TRESET), .nwe(NPSWR_STROBE), .noe(NPSEN));
`endif

// Instantiate an optional external 8-bit data memory of up to 1Mbyte
`ifdef muxed_pxram // Use a single memory interface bus
    initial $display("accessed via multiplexed interface");
   `ifdef sync_pmem
       cxram uXRAM (.RNW(NXRAMW), .NOE(NXRAMR), .NCS(1'b0), .CLK(CCLK),
                   .A(PROGA[(`XramALines - 1):0]), .DI(XRAMDO), .DO(PROGDI));
   `else
       assign NXRAMW_S = NXRAMW || CCLK;
       xram uXRAM (.NWR(NXRAMW_S), .NRD(NXRAMR),
                   .A(PROGA[(`XramALines - 1):0]), .DI(XRAMDO), .DO(PROGDI));
   `endif
`else              // Use separate program and data memory interfaces
   initial $display("External data memory accessed via separate interface");
   xram uXRAM (.NWR(NXRAMW), .NRD(NXRAMR),
               .A(XRAMA[(`XramALines - 1):0]), .DI(XRAMDO), .DO(XRAMDI));
`endif

// Instantiate a programmable wait state generator
wait_gen uWAIT (.ESFRDI(ESFRDI0), .MWAIT(MWAIT),
             .SFRSA(SFRSA), .DESTIN_A(DESTIN_A), .SFRWE(SFRWE), .SFRRE(SFRRE),
             .DESTIN_DO(DESTIN_DO), .XRAMA_EN(XRAMA_EN), .PROGA_EN(PROGA_EN),
             .NPSWR(NPSWR), .CLK(SCLK), .RESET(TRESET));

// Instantiate up to 104 optional external Special functional registers (ESFRs).
// These registers are the source for extended interrupts, NMI and configuration
// status.

`ifdef ExternalSFR
esfr uESFR  (.ESFRDI(ESFRDI1), .XINTR_SRC(XINTR_SRC), .NMI(NMI),
             .SFRSA(SFRSA), .DESTIN_A(DESTIN_A), .SFRWE(SFRWE), .SFRRE(SFRRE),
             .DESTIN_DO(DESTIN_DO), .XINTR_ACK(XINTR_ACK), .NMI_ACK(NMI_ACK),
             .CLK(PCLK), .RESET(TRESET));
`else
assign ESFRDI1 = 8'h00;
assign XINTR_SRC = 14'b00000000000000;
assign NMI = 0;
`endif

// combine ESFR sources
assign ESFRDI = ESFRDI0 | ESFRDI1;

// Logical model for an optional glitch-free and zero-skew clock gating network
// to reduce peripheral an idle mode power consumption.
`ifdef ClockGating
assign SCLK = XTAL1 || PDOWN;
assign CCLK = XTAL1 || NCCLKE;
assign PCLK = XTAL1 || NPCLKE;
`else
assign SCLK = XTAL1;
assign CCLK = XTAL1;
assign PCLK = XTAL1;
`endif

// Model crystal oscillator output pin
assign XTAL2 = ~XTAL1;

// Optionally hook up debug core
`ifdef IncludeOCI

  // Core may be reset by external pin or OCI core
  assign RESET = RST | JReset;

  // Multiplex debug code onto program data bus
  assign MuxedPROGDI[7:0] = DebugProg ? DebugPROGDI[7:0] : PROGDI[7:0];

`else

  assign RESET = RST;
  assign MuxedPROGDI = PROGDI;

`endif

// Tie off unused high address lines
`ifdef MemExtend
`else
  assign PROGA[19:16] = 4'b0000;
  assign XRAMA[19:16] = 4'b0000;
`endif

// Logical models for Port I/O Cells

assign PORT0I = PORT0;
assign PORT1I = PORT1;
assign PORT2I = PORT2;
assign PORT3I = PORT3;

// Port 0 pins have high impedance when in the inactive state.
assign PORT0[0] = PORT0O[0] ? 1'bz: 1'b0; 
assign PORT0[1] = PORT0O[1] ? 1'bz: 1'b0;
assign PORT0[2] = PORT0O[2] ? 1'bz: 1'b0;
assign PORT0[3] = PORT0O[3] ? 1'bz: 1'b0;
assign PORT0[4] = PORT0O[4] ? 1'bz: 1'b0;
assign PORT0[5] = PORT0O[5] ? 1'bz: 1'b0;
assign PORT0[6] = PORT0O[6] ? 1'bz: 1'b0;
assign PORT0[7] = PORT0O[7] ? 1'bz: 1'b0;

// Ports 1, 2 and 3 pins are pulled weakly high when not enabled.
assign PORT1[0] = NPORT1E[0] ? 1'bz: PORT1O[0];
assign PORT1[1] = NPORT1E[1] ? 1'bz: PORT1O[1];
assign PORT1[2] = NPORT1E[2] ? 1'bz: PORT1O[2];
assign PORT1[3] = NPORT1E[3] ? 1'bz: PORT1O[3];
assign PORT1[4] = NPORT1E[4] ? 1'bz: PORT1O[4];
assign PORT1[5] = NPORT1E[5] ? 1'bz: PORT1O[5];
assign PORT1[6] = NPORT1E[6] ? 1'bz: PORT1O[6];
assign PORT1[7] = NPORT1E[7] ? 1'bz: PORT1O[7];

assign PORT2[0] = NPORT2E[0] ? 1'bz: PORT2O[0];
assign PORT2[1] = NPORT2E[1] ? 1'bz: PORT2O[1];
assign PORT2[2] = NPORT2E[2] ? 1'bz: PORT2O[2];
assign PORT2[3] = NPORT2E[3] ? 1'bz: PORT2O[3];
assign PORT2[4] = NPORT2E[4] ? 1'bz: PORT2O[4];
assign PORT2[5] = NPORT2E[5] ? 1'bz: PORT2O[5];
assign PORT2[6] = NPORT2E[6] ? 1'bz: PORT2O[6];
assign PORT2[7] = NPORT2E[7] ? 1'bz: PORT2O[7];

assign PORT3[0] = NPORT3E[0] ? 1'bz: PORT3O[0];
assign PORT3[1] = NPORT3E[1] ? 1'bz: PORT3O[1];
assign PORT3[2] = NPORT3E[2] ? 1'bz: PORT3O[2];
assign PORT3[3] = NPORT3E[3] ? 1'bz: PORT3O[3];
assign PORT3[4] = NPORT3E[4] ? 1'bz: PORT3O[4];
assign PORT3[5] = NPORT3E[5] ? 1'bz: PORT3O[5];
assign PORT3[6] = NPORT3E[6] ? 1'bz: PORT3O[6];
assign PORT3[7] = NPORT3E[7] ? 1'bz: PORT3O[7];

// Tie off externbal timer2 inputs
assign EXT2_OVERFLOW = 1'b0;
assign EXT2_TCLK = 1'b0;
assign EXT2_RCLK = 1'b0;

// Program Counter List for Correlation Testing
integer corr_handle;
integer list_handle;

initial begin
  $timeformat(-9, 0, , 8);
  list_handle = $fopen("sim.lis");
  if (list_handle == 0) begin
    $display("Cannot open sim.lis");
    $finish;
  end

`ifdef CORRELATE
  corr_handle = $fopen("corr.lis");
  if (corr_handle == 0) begin
    $display("Cannot open corr.lis");
    $finish;
  end
`endif
  
  $fwrite(list_handle, "          P  P  P  P  P  X  S  E  M E E E              X N M R T S C P D D   P  P  P  P  N  N  N     P P N N     X X  X N N  S N  D  D N        S S S              X N I P N N D D D D\n");
  $fwrite(list_handle, "          O  O  O  O  R  R  O  S  X X X X              I M W E R C C C E E   O  O  O  O  P  P  P     R R P P     R R  R X X  O S  E  E D        F F F              I M D D P C E E E E\n");
  $fwrite(list_handle, "          R  R  R  R  O  A  U  F  S T T T              N I A S E L L L B B   R  R  R  R  O  O  O     O O S S     A A  A R R  U O  S  S E        R R R              N I L O C C B B B B\n");
  $fwrite(list_handle, "          T  T  T  T  G  M  R  R  _ 2 2 2              T   I E S K K K U U   T  T  T  T  R  R  R     G G E W     M M  M A A  R U  T  T S        S R W              T _ E W L L U U U U\n");
  $fwrite(list_handle, "          0  1  2  3  D  D  C  D  D _ _ _              R   T T E       G G   0  1  2  3  T  T  T     A A N R     A A  D M M  C R  I  I T        A E E              R A   N K K G G G G\n");
  $fwrite(list_handle, "          I  I  I  I  I  I  E  I  I O T R              _       T       R S   O  O  O  O  1  2  3       _           _  O R W  E C  N  N I                           _ C     E E A R P V\n");
  $fwrite(list_handle, "                            _       V C C              S               E T               E  E  E       E           E         _ E  _  _ N                           A K         C E F E\n");
  $fwrite(list_handle, "                            D       F L L              R               Q E                             N           N         A _  A  D _                           C           K T E C\n");
  $fwrite(list_handle, "                            I         K K              C                 P                                                     R     O W                           K             R T T\n");
  $fwrite(list_handle, "                                                                                                                               E       E                                            A C O\n");
  $fwrite(list_handle, "                                                                                                                                                                                     C H R\n");
  $fwrite(list_handle, "                                                                                                                                                                                     T    \n");
  $fwrite(list_handle, "\n");
  #(`TstrobeOffset);
  forever begin
    $fwrite(list_handle, "%t ", $time, 
                         "%h ", PORT0I, 
                         "%h ", PORT1I, 
                         "%h ", PORT2I, 
                         "%h ", PORT3I, 
                         "%h ", PROGDI, 
                         "%h ", XRAMDI, 
                         "%h ", SOURCE_DI, 
                         "%h ", ESFRDI, 
                         "%h ", MXS_DI, 
                         "%b ", EXT2_OVERFLOW,
                         "%b ", EXT2_TCLK,
                         "%b ", EXT2_RCLK,
                         "%b ", XINTR_SRC, 
                         "%h ", NMI, 
                         "%h ", MWAIT, 
                         "%h ", RESET, 
                         "%h ", TRESET, 
                         "%h ", SCLK, 
                         "%h ", CCLK, 
                         "%h ", PCLK,
                         "%h ", DebugReq,
                         "%h ", DebugStep);
    $fwrite(list_handle, " %h ", PORT0O, 
                         "%h ", PORT1O, 
                         "%h ", PORT2O, 
                         "%h ", PORT3O, 
                         "%h ", NPORT1E, 
                         "%h ", NPORT2E, 
                         "%h ", NPORT3E, 
                         "%h ", PROGA, 
                         "%h ", PROGA_EN, 
                         "%h ", NPSEN, 
                         "%h ", NPSWR, 
                         "%h ", XRAMA, 
                         "%h ", XRAMA_EN, 
                         "%h ", XRAMDO, 
                         "%h ", NXRAMR, 
                         "%h ", NXRAMW, 
                         "%h ", SOURCE_A, 
                         "%h ", NSOURCE_RE, 
                         "%h ", DESTIN_A, 
                         "%h ", DESTIN_DO, 
                         "%h ", NDESTIN_WE, 
                         "%h ", SFRSA, 
                         "%h ", SFRRE, 
                         "%h ", SFRWE, 
                         "%b ", XINTR_ACK, 
                         "%h ", NMI_ACK,
                         "%h ", IDLE, 
                         "%h ", PDOWN, 
                         "%h ", NPCLKE, 
                         "%h ", NCCLKE,
                         "%h ", DebugAck,
                         "%h ", DebugRetract,
                         "%h ", DebugPFetch,
                         "%h", DebugVector);
    $fwrite(list_handle, "\n");
    #`Thclk;
  end

end

`ifdef CORRELATE
// Program counter and ports 1 and 3 listing for correlation testing
always @(posedge SCLK) begin
    // Write record of the program address and ports 1 and 3 I/O for correlation
    // with the 40-pin reference part data.
    $fdisplay(corr_handle, "%h ", RESET,
                           "%h ", PORT1,
                           "%h ", PORT3,
                           "%h", PROGA[15:0] );
end
`endif

// Program bus monitor for crash detection
always @(posedge SCLK) begin
  if (^PROGA === 1'bx && ~TRESET) begin
    $display("Bus Error:   At time %t, program address indeterminate: %b",
             $time, PROGA);
    $finish;
  end
  else if (PROGA == `EXIT_ADDRESS) begin
    $display("Information: At time %t, program address reached exit loop",
             $time);
    #(`Thclk * 2.0);
    $finish;
  end
end


endmodule
